<?php
class NewFriendService extends AbstractService {
    /**
     * @var NewFriendService
     */
    private static $instance;

    /**
     * Get the instance of NewFriendService
     * @return NewFriendService
     */
    public static function get() {
        if (!self::$instance) {
            self::$instance = new NewFriendService();
        }
        return self::$instance;
    }

    /**
     * Construction.
     */
    protected function __construct() {
        parent::__construct();
    }

    /**
     * 处理用户创建时的逻辑
     * @param int $shardId
     * @return void
     */
    public function handleCreate($shardId) {

    }

    /**
     * 处理用户登录时的逻辑
     * @param int $userId
     * @return void
     */
    public function handleLogin($userId) {
        // do nothing
    }

    /**
     * 处理 service 对外提供的全量数据
     * @param int $userId
     * @return int
     */
    public function info($userId) {
        $friendList = $this->delFriendApplyList($userId);
        return count($friendList->getList());
    }

//    /**
//     * 获取好友列表
//     * @param $userId
//     * @param $start
//     * @param $end
//     * @return array
//     * @throws SzException
//     */
//    public function getFriendList1($userId,$start,$end) {
//        $friendPage = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'friend_page', true);
//        if (!isset($friendPage['value'])) {
//            return array();
//        }
//        $friendPage = $friendPage['value'];
//        if ($end < $start || ($end - $start) > $friendPage) {
//            return array();
//        }
//        /**
//         * @var $friendList NewFriendsVoList
//         */
//        $friendList = $this->delFriendApplyList($userId);
//        if (!$friendList) {
//            return array();
//        }
//        $data = $this->sortArrByManyField($friendList->toArray(),'canStealFlowers',SORT_DESC,'marking',SORT_DESC,'markingTime',SORT_DESC,'userLevel',SORT_DESC);
//        $len = count($data);
//        if ($len <= ($end - $start)) {
//            return $data;
//        }
//        $list = array();
//        $i = 1;
//        foreach ($data as $v) {
//            if ($i > $end) {
//                break;
//            }
//            if ($i >= $start) {
//                $list[] = $v;
//            }
//            $i++;
//        }
//        return $list;
//    }

    /**
     * 获取好友列表
     * @param $userId
     * @param $start
     * @param $end
     * @param $reqTime
     * @return array
     * @throws SzException
     */
    public function getFriendList($userId,$start,$end,$reqTime) {
        $friendList = $this->delFriendApplyList($userId);
        if (!$friendList || $end < $start || $start < 1 || $end < 1) {
            return array(
                'count' => 0,
                'friendList' => array()
            );
        }

        $result = array();
        $tempFriendsArr = $friendList->toArray();
        $count = count($tempFriendsArr);
        usort($tempFriendsArr, function ($a, $b){
            $criteria = array(
                'marking'=>'desc',
                'canStealFlowers'=>'desc',
                'flowerLevelExpireTime' => 'special',
            );
            foreach($criteria as $what => $order){
                if (isset($a[$what]) && isset($b[$what])){
                    if($a[$what] == $b[$what]){
                        continue;
                    }
                    if ($what != 'flowerLevelExpireTime'){
                        return (($order == 'desc') ? -1 : 1) * (($a[$what] < $b[$what]) ? -1 : 1);
                    }
                    else{
                        $serverTime = GameService::get()->getReqTime();
                        $hasAFlowerRank = $a['flowerLevelExpireTime'] < $serverTime ? -1 : 1;
                        $hasBFlowerRank = $b['flowerLevelExpireTime'] < $serverTime ? -1 : 1;
                        if ($hasAFlowerRank && $hasBFlowerRank) {
                            return ($a['flowerLevel'] < $b['flowerLevel']) ? -1 : 1;
                        }
                        if (!$hasBFlowerRank && !$hasAFlowerRank) {
                            return ($b['flowerLevel'] < $a['flowerLevel']) ? -1 : 1;
                        }
                        if ($hasAFlowerRank) {
                            return -1;
                        }
                        else {
                            return 1;
                        }
                    }
                }
            }
            return 0;
        });

        for ($i = $start - 1; $i < $end ; $i++){
            if (empty($tempFriendsArr[$i])){
                break;
            }
            $profile = SzPersister::get()->getVo($tempFriendsArr[$i]['friendId'], ModuleProfileConst::ORM_NAME_PROFILE);
            if (!$profile) {
                $friendList->deleteElement($tempFriendsArr[$i]['friendId'],false);
                continue;
            }
            if ($i < $end) {
                $result[] = $this->getUserInfo($tempFriendsArr[$i]['friendId'],$tempFriendsArr[$i]['userId'],$tempFriendsArr[$i]['isNew'],$tempFriendsArr[$i]['inviteId'],$tempFriendsArr[$i]['isGetInviteReward'],$tempFriendsArr[$i]['marking'],$tempFriendsArr[$i]['markingTime']);
            }
        }

        SzPersister::get()->setVoList($friendList);
        return array(
            'count' => $count,
            'friendList' => $result
        );
    }

    /**
     * 获取邀请好友阶段奖励列表
     * @param $userId
     * @return array
     * @throws SzException
     */
    public function getInviteFriendList($userId) {
        $data = array(
            'inviteFriendList' => array(),
            'num' => 0
        );
        /**
         * @var $friendList NewFriendsVoList
         * @var $friend NewFriendsVo
         */
        $friendList = $this->delFriendApplyList($userId);
        if (!$friendList) {
            return $data;
        }
        $inviteSettings = SzConfig::get()->loadAppConfig(GameConst::CONFIG_INVITE, null, true);
        if (!$inviteSettings) {
            return $data;
        }
        $count = 0;
        foreach ($friendList->getList() as $friend) {
            if (isset($inviteSettings[$friend->getInviteId()])) {
                $count++;
                $data['inviteFriendList'][] = $this->getUserInfo($friend->getFriendId(),$userId,$friend->getIsNew(),$friend->getInviteId(),$friend->getIsGetInviteReward(),$friend->getMarking(),$friend->getMarkingTime());
            }
        }
        $data['num'] = $this->getInviteNum($userId,$count);

        return $data;
    }

    /**
     * 设置标识
     * @param $userId
     * @param $friendId
     * @param $marking
     * @param $reqTime
     * @return bool
     * @throws SzException
     */
    public function setMarking($userId,$friendId,$marking,$reqTime) {
        /**
         * @var $friendList NewFriendsVoList
         * @var $friend NewFriendsVo
         */
        $friendList =  $this->delFriendApplyList($userId);
        $friend = $friendList->getElement($friendId,false);
        if (!$friend) {
            return false;
        }
        if ($marking) {
            $marking = 1;
        } else {
            $marking = 0;
        }

        if ($friend->getMarking() == $marking) {
            return true;
        }
        $friend->setMarking($marking);
        $friend->setMarkingTime($reqTime);
        $friendList->updateElement($friendId,$friend);
        SzPersister::get()->setVoList($friendList);
        return true;
    }

    /**
     * 批量申请好友
     * @param $userId
     * @param $friendIds
     * @param $reqTime
     * @return bool
     * @throws SzException
     */
    public function applyFriend($userId,$friendIds,$type,$reqTime) {
        $upper_limit_of_friends = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'upper_limit_of_friends', true);
        $upper_limit_of_friends = $upper_limit_of_friends['value'];
        /**
         * @var $friendList NewFriendsVoList
         */
        $friendList = $this->delFriendApplyList($userId);
        if ($upper_limit_of_friends <= count($friendList->getList())) {
            return 0;
        }

        $redisDb = SzDbFactory::get()->getDb(null, SzAbstractDb::DB_TYPE_REDIS);
        $redisDb1 = SzDbFactory::get()->getDb($userId, SzAbstractDb::DB_TYPE_REDIS);
        foreach ($friendIds as $friendId) {
            $profile = SzPersister::get()->getVo($friendId, ModuleProfileConst::ORM_NAME_PROFILE);
            if (!$type && !$profile) {
                return 1;
            } else if (!$profile) {
                continue;
            }

            $friendInfo = $friendList->getElement($friendId,false);
            if ( ($friendInfo || $userId == $friendId) && !$type) {
                return 2;
            } else if ($friendInfo || $userId == $friendId) {
                continue;
            }
            $bool = $redisDb->hGet(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$friendId,$userId);
            if ($bool && !$type) {
                return 3;
            } else if ($bool) {
                continue;
            }
            $redisDb->hSet(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$friendId,$userId,$reqTime);
            if ($type && $redisDb1->hGet(GameConst::CACHE_KEY_NEW_FRIEND_RECOMMEND.$userId,$friendId)) {
                $redisDb1->hSet(GameConst::CACHE_KEY_NEW_FRIEND_RECOMMEND.$userId,$friendId,0);
            }
            // 记录日志：申请添加好友
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
                'clientData' => array(
                    'tid' => 'Module:friends|action:apply|',
                    'item' => $friendId,
                    'value' => 1,
                )
            ));
        }
        return 4;
    }

    /**
     * 批量拒绝好友
     * @param $userId
     * @param $friendIds
     * @param $reqTime
     * @return bool
     * @throws SzException
     */
    public function rejectFriend($userId,$friendIds) {
        /**
         * @var $friendList NewFriendsVoList
         */
        $redisDb = SzDbFactory::get()->getDb(null, SzAbstractDb::DB_TYPE_REDIS);
        foreach ($friendIds as $friendId) {
            $redisDb->hDel(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$userId,$friendId);
            // 记录日志：拒绝添加好友申请
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
                'clientData' => array(
                    'tid' => 'Module:friends|action:reject|',
                    'item' => $friendId,
                    'value' => 1,
                )
            ));
        }
        return true;
    }

    /**
     * 批量同意好友
     * @param $userId
     * @param $friendIds
     * @return bool
     * @throws SzException
     */
    public function agreeFriend($userId,$friendIds,$reqTime) {
        /**
         * @var $friendList NewFriendsVoList
         * @var $userFriendList NewFriendsVoList
         */
        $friendList = $this->delFriendApplyList($userId);
        $upper_limit_of_friends = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'upper_limit_of_friends', true);
        $upper_limit_of_friends = $upper_limit_of_friends['value'];
        if ( (count($friendList->getList()) + count($friendIds)) > $upper_limit_of_friends) {
            return false;
        }

        $redisDb = SzDbFactory::get()->getDb(null, SzAbstractDb::DB_TYPE_REDIS);
        foreach ($friendIds as $friendId) {
            if ($friendList->getElement($friendId,false)) {
                $redisDb->hDel(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$userId,$friendId);
                continue;
            }
            if (count(SzPersister::get()->getVoList($friendId, GameConst::ORM_NAME_NEW_FRIEND)) >= $upper_limit_of_friends) {
                $redisDb->hDel(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$userId,$friendId);
                continue;
            }

            $friendVo = new NewFriendsVo($userId, $friendId, 1, -1, 0, 0,$reqTime,0,0,true);
            $friendList->addElement($friendVo);
            $friendList->setElement($friendId,$friendVo);
            $userFriendList = SzPersister::get()->getVoList($friendId, GameConst::ORM_NAME_NEW_FRIEND);
            if (!$userFriendList->getElement($friendId,false)) {
                $userFriendVo = new NewFriendsVo($friendId,$userId, 1, -1, 0, 0,$reqTime,0,0,true);
                $userFriendList->addElement($userFriendVo);
                $userFriendList->setElement($userId,$userFriendVo);
                SzPersister::get()->setVoList($userFriendList);
                // 记录日志：接受好友添加申请
                StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
                    'clientData' => array(
                        'tid' => 'Module:friends|action:accept|',
                        'item' => $friendId,
                        'value' => 1,
                    )
                ));
            }
            $redisDb->hDel(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$userId,$friendId);
        }

        SzPersister::get()->setVoList($friendList);
        return true;
    }

    /**
     * 删除好友
     * @param $userId
     * @param $friendIds
     * @return bool
     * @throws SzException
     */
    public function delFriend($userId,$friendIds) {
        /**
         * @var $friendList NewFriendsVoList
         * @var $userFriendList NewFriendsVoList
         * @var $friend NewFriendsVo
         * @var $userFriend NewFriendsVo
         * @var $eventInviteList EventInviteVoList
         */
        $friendList = $this->delFriendApplyList($userId);
        if (!$friendList) {
            return true;
        }

        $eventInviteList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_EVENT_INVITE);

        foreach ($friendIds as $friendId) {
            $friend = $friendList->getElement($friendId,false);
            if (!$friend) {
                continue;
            }
            if ($friend->getInviteId() == 14001 && !$eventInviteList->getElement(6,false)) {
                return false;
            }

            $userFriendList = SzPersister::get()->getVoList($friendId, GameConst::ORM_NAME_NEW_FRIEND);
            $userFriend = $userFriendList->getElement($userId,false);
            if ($userFriend && $userFriend->getInviteId() == 14001) {
                $userEventInviteList = SzPersister::get()->getVoList($friendId, GameConst::ORM_NAME_EVENT_INVITE);
                if (!$userEventInviteList->getElement(6,false)) {
                    return false;
                }
            }

            $friendList->deleteElement($friendId,false);

            $userFriendList->deleteElement($userId,false);
            SzPersister::get()->setVoList($userFriendList);
            // 记录日志：删除好友
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
                'clientData' => array(
                    'tid' => 'Module:friends|action:delete|',
                    'item' => $friendId,
                    'value' => 1,
                )
            ));
        }
        SzPersister::get()->setVoList($friendList);
        return true;
    }

    /**
     * 获取好友推荐列表
     * @param $userId
     * @param $reqTime
     * @return array
     * @throws SzException
     */
    public function getFriendRecommendList($userId,$reqTime) {
        $result = array();
        $redisDb = SzDbFactory::get()->getDb($userId, SzAbstractDb::DB_TYPE_REDIS);
        $recommend_friends_to_refresh = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'recommend_friends_to_refresh', true);
        if (!$recommend_friends_to_refresh) {
            return array();
        }
        $recommend_friends_to_refresh = explode(',',$recommend_friends_to_refresh['value']);
        array_unshift($recommend_friends_to_refresh,0);
        $num = count($recommend_friends_to_refresh);
        if (!$num) {
            return array();
        }
        $hour = date('H',$reqTime);
        $refreshHour = 0;
        for($i=0;$i<$num;$i++) {
            if ($hour < $recommend_friends_to_refresh[$i]) {
                break;
            } else if ($hour == $recommend_friends_to_refresh[$i]) {
                $refreshHour = $hour;
                break;
            } else {
                $refreshHour = $recommend_friends_to_refresh[$i];
            }
        }
        $list = $redisDb->hGetAll(GameConst::CACHE_KEY_NEW_FRIEND_RECOMMEND.$userId);
        if (!$list) {
            $result = $this->getRecommendList($userId,$redisDb, $refreshHour,$reqTime);
        } else {
            if ($list['refreshHour'] ==  $refreshHour && date('Ymd',$list['refreshTime']) == date('Ymd',$reqTime)) {
                unset($list['refreshTime']);
                unset($list['refreshHour']);
                foreach ($list as $friendUserId=>$status) {
                    if (!$status) {
                        continue;
                    }
                    $profileInfoList = SzPersister::get()->getVoList($friendUserId, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
                    $temp = array(
                        'userId' => $friendUserId,
                        'userLevel' => UserService::get()->getUserLevel($friendUserId),
                        'townName' => UserService::get()->getTownName($friendUserId, $profileInfoList),
                        'headImgId' => UserService::get()->getHeadIcon($friendUserId, $profileInfoList),
                        'gender' => UserService::get()->getGender($friendUserId,$profileInfoList),
                        'flowerLevel' => UserService::get()->getFlowerLevel($friendUserId,$profileInfoList),
                        'flowerLevelExpireTime' => UserService::get()->getFlowerLevelExpireTime($friendUserId,$profileInfoList),
                    );

                    //获取玩家的头像框数据
                    $profileInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_HEAD_FRAME,false);
                    if (!$profileInfo){
                        $temp['headFrame'] = 0;
                    }
                    else{
                        $temp['headFrame'] = $profileInfo->getInfo();
                    }

                    $result[] = $temp;
                }
            } else {
                $redisDb->delete(GameConst::CACHE_KEY_NEW_FRIEND_RECOMMEND.$userId);
                $result = $this->getRecommendList($userId,$redisDb, $refreshHour,$reqTime);
            }
        }
        return $result;
    }

    public function applyFriendList($userId,$reqTime) {
        $this->delFriendApplyList($userId);
        $redisDb = SzDbFactory::get()->getDb($userId, SzAbstractDb::DB_TYPE_REDIS);
        $list = $redisDb->hGetAll(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$userId);
        $result = array();
        if ($list) {
            foreach ($list as $friendUserId=>$time) {
                $profileInfoList = SzPersister::get()->getVoList($friendUserId, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
                if (!$profileInfoList) {
                    continue;
                }
                $temp= array(
                    'userId' => $friendUserId,
                    'userLevel' => UserService::get()->getUserLevel($friendUserId),
                    'townName' => UserService::get()->getTownName($friendUserId, $profileInfoList),
                    'headImgId' => UserService::get()->getHeadIcon($friendUserId, $profileInfoList),
                    'gender' => UserService::get()->getGender($friendUserId,$profileInfoList),
                    'flowerLevel' => UserService::get()->getFlowerLevel($friendUserId,$profileInfoList),
                    'flowerLevelExpireTime' => UserService::get()->getFlowerLevelExpireTime($friendUserId,$profileInfoList),
                );
                //获取玩家的头像框数据
                $profileInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_HEAD_FRAME,false);
                if (!$profileInfo){
                    $temp['headFrame'] = 0;
                }
                else{
                    $temp['headFrame'] = $profileInfo->getInfo();
                }

                $result[] = $temp;
            }
        }


        return $result;
    }
    /*************************************************************************************************/

    /**
     * 多字段排序
     * @return array
     */
   private function sortArrByManyField() {
        $args = func_get_args();
        if(empty($args)){
            return array();
        }
        $arr = array_shift($args);
        if(!is_array($arr)){
            return array();
        }
        foreach($args as $key => $field){
            if(is_string($field)){
                $temp = array();
                foreach($arr as $index=> &$v){
                    if (!isset($v['canStealFlowers'])) {
                        $v = $this->getUserInfo($v['friendId'],$v['userId'],$v['isNew'],$v['inviteId'],$v['isGetInviteReward'],$v['marking'],$v['markingTime']);
                    }
                    $temp[$index] = $v[$field];
                }
                $args[$key] = $temp;
            }
        }
        $args[] = &$arr;
        call_user_func_array('array_multisort',$args);
        return array_pop($args);
    }

    /**
     * 获取好友信息
     * @param $friendId
     * @param $userId
     * @param $isNew
     * @param $inviteId
     * @param $isGetInviteReward
     * @param $marking
     * @param $markingTime
     * @return array
     * @throws SzException
     */
    public function getUserInfo($friendId,$userId,$isNew,$inviteId,$isGetInviteReward,$marking,$markingTime) {
        $profileInfoList = SzPersister::get()->getVoList($friendId, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
        $res = array(
            'userId' => $friendId,
            'userLevel' => UserService::get()->getUserLevel($friendId),
            'townName' => UserService::get()->getTownName($friendId, $profileInfoList),
            'headImgId' => UserService::get()->getHeadIcon($friendId, $profileInfoList),
            'gender' => UserService::get()->getGender($friendId,$profileInfoList),
            'isNew' => $isNew,
            'inviteId' => $inviteId,
            'isGetInviteReward' => $isGetInviteReward,
            'canStealFlowers' => $this->canStealFlowers($friendId,$userId),
            'marking' => $marking,
            'markingTime' => $markingTime,
            'monthCard' => UserService::get()->getMonthCard($friendId,$profileInfoList),
            'flowerLevel' => UserService::get()->getFlowerLevel($friendId,$profileInfoList),
            'flowerLevelExpireTime' => UserService::get()->getFlowerLevelExpireTime($friendId,$profileInfoList),
        );

        //获取玩家的头像框数据
        $profileInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_HEAD_FRAME,false);
        if (!$profileInfo){
            $res['headFrame'] = 0;
        }
        else{
            $res['headFrame'] = $profileInfo->getInfo();
        }

        return $res;
    }

    /**
     * 是否可以偷花
     * @param $friendId
     * @param $userId
     * @return int
     */
    private function canStealFlowers($friendId, $userId) {
        $totalCount = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'umberOfMutualaid', true);
        //获取当天交互次数
        $friendCount = FriendService::get()->getFriendHandleInfo($userId, $friendId,$totalCount);
        if ($friendCount < $totalCount['value']) {
            if (PlantService::get()->isCanStealFlower($userId, $friendId)) {
                return 1;
            }
        }
        return 0;
    }

    /**
     * 删除过期好友&&已添加的好友
     * @param $userId
     * @return NewFriendsVoList
     * @throws SzException
     */
    private function delFriendApplyList($userId) {
        $reqTime = GameService::get()->getReqTime();
        /**
         * @var $friendList NewFriendsVoList
         */
        $friendList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND);
        if (!$friendList) {
            return $friendList;
        }
        $redisDb = SzDbFactory::get()->getDb(null, SzAbstractDb::DB_TYPE_REDIS);
        $list = $redisDb->hGetAll(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$userId);
        if (!$list) {
            return $friendList;
        }
        foreach ($list as $friendId=>$time) {
            if ($reqTime >= ($time + SzTime::HOURS24) || $friendList->getElement($friendId,false)) {
                $redisDb->hDel(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$userId,$friendId);
            }
        }
        return $friendList;
    }

    /**
     * @param $userId
     * @param $redisDb
     * @return array
     * @throws SzException
     */
    public function getRecommendList($userId,$redisDb,$refreshHour,$reqTime) {
        /**
         * @var $friendList NewFriendsVoList
         * @var $userFriendList NewFriendsVoList
         * @var $redisDb SzRedisDb
         */
        $redisDb1 = SzDbFactory::get()->getDb(null, SzAbstractDb::DB_TYPE_REDIS);
        $listCount = 10;
        // 数据库的分库中随机取出一个shareId，然后
        $serversConfig = SzConfig::get()->loadAppConfig('database', 'MySql');
        $shardId = mt_rand(0, count($serversConfig) - 1);

        $instance = new SzMySqlDb($serversConfig[$shardId]);

        $moduleProfiles = $instance->select("SELECT `userId`, `level` FROM `module_profile` WHERE `userId` != {$userId} ORDER BY `lastLoginTime` DESC limit " . ($listCount * 100));
        shuffle($moduleProfiles);
        $result = [];
        $friendList = $this->delFriendApplyList($userId);

        //玩家等级
        $userLevel =  UserService::get()->getUserLevel($userId);
        $levelLimit = GameConst::NEW_FRIEND_RECOMMEND_LEVEL;
        $minLevel = ($userLevel - $levelLimit) >0 ? ($userLevel - $levelLimit) : 1;
        $maxLevel = $userLevel + $levelLimit;

        foreach ($moduleProfiles as $profile) {
            $friendUserId = $profile['userId'];
            $friendLevel =  UserService::get()->getUserLevel($friendUserId);
            if (in_array($friendUserId, $friendList->toArray())) {
                continue;
            }
            if ($redisDb1->hGet(GameConst::CACHE_KEY_NEW_FRIEND_APPLY.$userId,$friendUserId)) {
                continue;
            }

            if ($friendLevel > $maxLevel  || $friendLevel <$minLevel) {
                continue;
            }

            $profileInfoList = SzPersister::get()->getVoList($friendUserId, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
            $redisDb->hSet(GameConst::CACHE_KEY_NEW_FRIEND_RECOMMEND.$userId,$friendUserId,1);
            $temp = array(
                'userId' => $friendUserId,
                'userLevel' => UserService::get()->getUserLevel($friendUserId),
                'townName' => UserService::get()->getTownName($friendUserId, $profileInfoList),
                'headImgId' => UserService::get()->getHeadIcon($friendUserId, $profileInfoList),
                'gender' => UserService::get()->getGender($friendUserId,$profileInfoList),
            );
            //获取玩家的头像框数据
            $profileInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_HEAD_FRAME,false);
            if (!$profileInfo){
                $temp['headFrame'] = 0;
            }
            else{
                $temp['headFrame'] = $profileInfo->getInfo();
            }

            $result[] = $temp;
            if (count($result) >= $listCount) {
                break;
            }
        }
        $redisDb->hSet(GameConst::CACHE_KEY_NEW_FRIEND_RECOMMEND.$userId,'refreshHour',$refreshHour);
        $redisDb->hSet(GameConst::CACHE_KEY_NEW_FRIEND_RECOMMEND.$userId,'refreshTime',$reqTime);
        return $result;
    }

    /**
     * @param $userId
     * @param $inviteNum
     * @return mixed
     * @throws SzException
     */
    public function getInviteNum($userId,$inviteNum,$profileInfoList = null,$inviteNumInfo = null) {
        /**
         * @var $inviteCountInfo ModuleProfileInfoVo
         * @var $inviteNumInfo ModuleProfileInfoVo
         */
        if (is_null($profileInfoList) && is_null($inviteNumInfo)) {
            $profileInfoList = SzPersister::get()->getVoList($userId, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
            $inviteNumInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_INVITE_NUM,false);
        }
        if ($inviteNumInfo) {
            if ($inviteNum > (int)$inviteNumInfo->getRawInfo()) {
                $inviteNumInfo->setInfo($inviteNum);
                $profileInfoList->updateElement(GameConst::USER_INFO_TYPE_INVITE_NUM, $inviteNumInfo);
                SzPersister::get()->setVoList($profileInfoList);
            } else {
                $inviteNum = (int)$inviteNumInfo->getRawInfo();
            }
        } else {
            $inviteCountInfo = $profileInfoList->getElement( GameConst::USER_INFO_TYPE_INVITE_COUNT,false);
            if ($inviteCountInfo) {
                foreach ($inviteCountInfo->getRawInfo() as $num) {
                    if ($num > $inviteNum) {
                        $inviteNum = $num;
                    }
                }
            }
            $inviteNumInfo =  new ModuleProfileInfoVo(
                $userId,
                GameConst::USER_INFO_TYPE_INVITE_NUM,
                (int)$inviteNum,
                GameService::get()->getReqTime(),
                true
            );
            $profileInfoList->addElement($inviteNumInfo);
            $profileInfoList->setElement(GameConst::USER_INFO_TYPE_INVITE_NUM, $inviteNumInfo);
            SzPersister::get()->setVoList($profileInfoList);
        }
        return $inviteNum;
    }

    /**
     * 初始化新功能好友邀请
     * @param $userId
     * @throws SzException
     */
    public function initFriendInvite($userId) {
        $inviteFriendMaxNum = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'inviteFriendMaxNum', true);

        if (!$inviteFriendMaxNum) {
            return;
        }
        $inviteFriendMaxNum = $inviteFriendMaxNum['value'];
        /**
         * @var $friendList NewFriendsVoList
         * @var $friend NewFriendsVo
         * @var $newFriendInviteList NewFriendInviteVoList
         * @var $newFriendInvite NewFriendInviteVo
         * @var $newFriendInviteInfoList NewFriendInviteInfoVoList
         * @var $newFriendInviteInfo  NewFriendInviteInfoVo
         */
        $newFriendInviteInfoList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE_INFO);
        $newFriendInviteInfo = $newFriendInviteInfoList->getElement(GameConst::INVITE_FRIEND_PRIMARY_KEY,false);
        if ($newFriendInviteInfo) {
            return;
        }

        $friendList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND);
        $inviteSettings = SzConfig::get()->loadAppConfig(GameConst::CONFIG_INVITE, null, true);
        if (!$inviteSettings) {
            return;
        }

        $data = array();
        foreach ($friendList->getList() as $friend) {
            if (isset($inviteSettings[$friend->getInviteId()])) {
                $data[$friend->getFriendId()] = UserService::get()->getUserLastLoginTime($friend->getFriendId());
            }
        }

        if ($data) {
            arsort($data);
        }
        $delFriendIds = array();
        $newFriendInviteList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE);
        if ($newFriendInviteList->toArray()) {
            $profileInfoList = SzPersister::get()->getVoList($userId, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
            $inviteStatusProfileInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_INVITE_STATUS, false);

            if (!$inviteStatusProfileInfo) {
                $inviteStatusProfileInfo = new ModuleProfileInfoVo(
                    $userId,
                    GameConst::USER_INFO_TYPE_INVITE_STATUS,
                    1,
                    GameService::get()->getReqTime(),
                    true
                );
                $profileInfoList->addElement($inviteStatusProfileInfo);
                $profileInfoList->setElement(GameConst::USER_INFO_TYPE_INVITE_STATUS,$inviteStatusProfileInfo);
                SzPersister::get()->setVoList($profileInfoList);
                foreach ($newFriendInviteList->toArray() as $val) {
                    $delFriendIds[$val['friendId']] = $val['friendId'];
                }
                $newFriendInviteInfoList->deleteElement(1,false);
            }
        }

        $i = 1;
        if ($data) {
            foreach ($data as $friendId=>$level) {
                if ($i > $inviteFriendMaxNum) {
                    break;
                }
                $newFriendInvite = $newFriendInviteList->getElement($friendId,false);
                if (in_array($friendId,$delFriendIds)) {
                    unset($delFriendIds[$friendId]);
                }
                if ($newFriendInvite) {
                    $newFriendInvite->setLastLevel(0);
                    $newFriendInvite->setInviteTime(GameService::get()->getReqTime());
                    $newFriendInviteList->updateElement($friendId,$newFriendInvite);
                    continue;
                }
                $newFriendInvite = new NewFriendInviteVo($userId,$friendId,0,GameService::get()->getReqTime(),true);
                $newFriendInviteList->addElement($newFriendInvite);
                $newFriendInviteList->setElement($friendId,$newFriendInvite);
                $i++;
            }
        }

        if ($delFriendIds) {
            foreach ($delFriendIds as $friendId) {
                $newFriendInviteList->deleteElement($friendId,true);
            }
        }

        $newFriendInviteInfo = new NewFriendInviteInfoVo($userId,GameConst::INVITE_FRIEND_PRIMARY_KEY,[],0,($i - 1),true);
        $newFriendInviteInfoList->addElement($newFriendInviteInfo);
        $newFriendInviteInfoList->setElement(GameConst::INVITE_FRIEND_PRIMARY_KEY,$newFriendInviteInfo);

        SzPersister::get()->setVoList($newFriendInviteInfoList);
        SzPersister::get()->setVoList($newFriendInviteList);

        return;
    }

    /**
     * 邀请好友信息
     * @param $userId
     * @return array
     * @throws SzException
     */
    public function inviteFriendInfo($userId) {
        /**
         * @var $newFriendInviteList NewFriendInviteVoList
         * @var $newFriendInvite NewFriendInviteVo
         * @var $newFriendInviteInfoList NewFriendInviteInfoVoList
         * @var $newFriendInviteInfo  NewFriendInviteInfoVo
         */
        $newFriendInviteInfoList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE_INFO);
        $newFriendInviteInfo = $newFriendInviteInfoList->getElement(GameConst::INVITE_FRIEND_PRIMARY_KEY);

        $newFriendInviteList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE);

        $level = 0;

        $inviteLevelSettings = SzConfig::get()->loadAppConfig(GameConst::CONFIG_GAME_INVITE_LEVEL,null,true);

        foreach ($newFriendInviteList->toArray() as $info) {
            $newFriendInvite = $newFriendInviteList->getElement($info['friendId'],false);
            if (!$newFriendInvite) {
                continue;
            }
            $userLevel = UserService::get()->getUserLevel($info['friendId']);
            if ($info['lastLevel'] != $userLevel && $userLevel > $info['lastLevel']) {

                if (isset($inviteLevelSettings[$userLevel]) && (isset($inviteLevelSettings[$info['lastLevel']]) || !$info['lastLevel'])) {
                    $newFriendInvite->setLastLevel($userLevel);
                    $newFriendInviteList->updateElement($info['friendId'],$newFriendInvite);

                    for ($i = ($info['lastLevel'] + 1); $i<=$userLevel; $i++) {
                        if (isset($inviteLevelSettings[$i])) {
                            $level += $inviteLevelSettings[$i]['inviteLevel'];
                        }
                    }
                }
            }
        }

        $inviteFriendMaxLevel = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'inviteFriendMaxLevel', true);

        if ($inviteFriendMaxLevel) {
            $inviteFriendMaxLevel = $inviteFriendMaxLevel['value'];
        } else {
            $inviteFriendMaxLevel = 200;
        }

        if ( ($level + $newFriendInviteInfo->getLevel()) >= $inviteFriendMaxLevel) {
            $newFriendInviteInfo->setLevel($inviteFriendMaxLevel);
        } else {
            $newFriendInviteInfo->updateLevel($level);
        }


        $newFriendInviteInfoList->updateElement(GameConst::INVITE_FRIEND_PRIMARY_KEY,$newFriendInviteInfo);

        SzPersister::get()->setVoList($newFriendInviteInfoList);
        SzPersister::get()->setVoList($newFriendInviteList);

        $newFriendInviteInfo = $newFriendInviteInfo->toArray();

        $newFriendInviteInfo['info'] = $newFriendInviteInfo['info'] ? $newFriendInviteInfo['info']  : array();

        $newFriendInvite = array();
        if ($newFriendInviteList->toArray()) {
            foreach ($newFriendInviteList->toArray() as $k=>$v) {
                $newFriendInvite[$k] = $v;
                $profileInfoList = SzPersister::get()->getVoList($k, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
                $newFriendInvite[$k]['userLevel'] =  UserService::get()->getUserLevel($k);
                $newFriendInvite[$k]['townName'] =  UserService::get()->getTownName($k, $profileInfoList);
                $newFriendInvite[$k]['headImgId'] =  UserService::get()->getHeadIcon($k, $profileInfoList);
            }
        }

        return array(
            'newFriendInviteInfo' => $newFriendInviteInfo,
            'newFriendInvite' => $newFriendInvite
        );
    }

    /**
     * 领取阶段奖励
     * @param $userId
     * @param $id
     * @return bool
     * @throws SzException
     */
    public function inviteFriendReward($userId,$id) {
        /**
         * @var $newFriendInviteInfoList NewFriendInviteInfoVoList
         * @var $newFriendInviteInfo  NewFriendInviteInfoVo
         */
        $newFriendInviteInfoList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE_INFO);
        $newFriendInviteInfo = $newFriendInviteInfoList->getElement(GameConst::INVITE_FRIEND_PRIMARY_KEY);

        $info = $newFriendInviteInfo->getRawInfo();
        $info = $info ? $info : array();

        if (in_array($id,$info)) {
            throw new SzException(90007);
        }

        $inviteRewardSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_GAME_INVITE_REWARD, $id, true);

        if (!$inviteRewardSetting) {
            throw new SzException(80001,GameConst::CONFIG_GAME_INVITE_REWARD.'-'.$id);
        }

        if ($inviteRewardSetting['requiresLevel'] > $newFriendInviteInfo->getLevel()) {
            throw new SzException(90065);
        }

        $output = '';
        foreach ($inviteRewardSetting['oneTimeReward'] as $entryId=>$count) {
            GameService::get()->handleEntity($userId, $entryId, $count, true, true);
            $output .= $entryId.':'.$count.'|';
        }

        $info[] = $id;
        $newFriendInviteInfo->setInfo($info);
        $newFriendInviteInfoList->updateElement(GameConst::INVITE_FRIEND_PRIMARY_KEY,$newFriendInviteInfo);
        SzPersister::get()->setVoList($newFriendInviteInfoList);

        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:invite|action:onceGift|',
                'item' => $newFriendInviteInfo->getLevel().'&'.$id,
                'value' => 1
            )
        ));

        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_OUTPUT, array(
            'clientData' => array(
                'tid' => $output,
                'item' => 'invite_onceGift'
            )
        ));

        return true;
    }

    /**
     * 每日奖励领取
     * @param $userId
     * @param $id
     * @param $reqTime
     * @return bool
     * @throws SzException
     */
    public function inviteFriendDailyReward($userId,$id, $reqTime) {
        /**
         * @var $newFriendInviteInfoList NewFriendInviteInfoVoList
         * @var $newFriendInviteInfo  NewFriendInviteInfoVo
         */
        $newFriendInviteInfoList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE_INFO);
        $newFriendInviteInfo = $newFriendInviteInfoList->getElement(GameConst::INVITE_FRIEND_PRIMARY_KEY);

        if (date('Ymd',$reqTime) == date('Ymd',$newFriendInviteInfo->getDailyTime())) {
            throw new SzException(90007);
        }

        $inviteDailyRewardSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_GAME_INVITE_DAILY_REWARD, $id, true);

        if (!$inviteDailyRewardSetting) {
            throw new SzException(80001,GameConst::CONFIG_GAME_INVITE_DAILY_REWARD.'-'.$id);
        }

        if ($inviteDailyRewardSetting['requiresLevel'] > $newFriendInviteInfo->getLevel()) {
            throw new SzException(90065);
        }

        $output = '';
        foreach ($inviteDailyRewardSetting['reward'] as $entryId=>$count) {
            GameService::get()->handleEntity($userId, $entryId, $count, true, true);
            $output .= $entryId.':'.$count.'|';
        }

        $newFriendInviteInfo->setDailyTime($reqTime);
        $newFriendInviteInfoList->updateElement(GameConst::INVITE_FRIEND_PRIMARY_KEY,$newFriendInviteInfo);
        SzPersister::get()->setVoList($newFriendInviteInfoList);

        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:invite|action:dailyGift|',
                'item' => $newFriendInviteInfo->getLevel().'&'.$id,
                'value' => 1
            )
        ));

        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_OUTPUT, array(
            'clientData' => array(
                'tid' => $output,
                'item' => 'invite_dailyGift'
            )
        ));

        return true;
    }

    /**
     * 删除好友
     * @param $userId
     * @param $friendId
     * @return bool
     * @throws SzException
     */
    public function deleteInviteFriend($userId,$friendId) {
        /**
         * @var $newFriendInviteList NewFriendInviteVoList
         */
        $newFriendInviteList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE);

        $newFriendInviteList->deleteElement($friendId,false);

        SzPersister::get()->setVoList($newFriendInviteList);

        /**
         * @var $newFriendInviteInfoList NewFriendInviteInfoVoList
         * @var $newFriendInviteInfo  NewFriendInviteInfoVo
         * @var $profile ProfileVo
         */
        $newFriendInviteInfoList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE_INFO);
        $newFriendInviteInfo = $newFriendInviteInfoList->getElement(GameConst::INVITE_FRIEND_PRIMARY_KEY);

        $profile = SzPersister::get()->getVo($friendId, ModuleProfileConst::ORM_NAME_PROFILE);
        if (!$profile) {
            return true;
        }
        $level = $profile->getLevel();
        $userLevel = $newFriendInviteInfo->getLevel();


        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:invite|action:delete|',
                'item' => $userLevel.'&'.$friendId.'&'.$level,
                'value' => 1
            )
        ));

        return true;
    }

    /**
     * 添加好友
     * @param $userId
     * @param $friendId
     * @throws SzException
     */
    public function addInviteFriend($userId,$friendId) {
        /**
         * @var $newFriendInviteList NewFriendInviteVoList
         * @var $newFriendInviteInfoList NewFriendInviteInfoVoList
         * @var $newFriendInviteInfo  NewFriendInviteInfoVo
         */
        $newFriendInviteList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE);

        $inviteFriendMaxNum = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'inviteFriendMaxNum', true);
        if (!$inviteFriendMaxNum) {
            return;
        }
        $inviteFriendMaxNum = $inviteFriendMaxNum['value'];

        if (count($newFriendInviteList->toArray()) >= $inviteFriendMaxNum) {
            return;
        }

        $newFriendInvite = new NewFriendInviteVo($userId,$friendId,0,GameService::get()->getReqTime(),true);
        $newFriendInviteList->addElement($newFriendInvite);
        $newFriendInviteList->setElement($friendId,$newFriendInvite);

        $newFriendInviteInfoList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_FRIEND_INVITE_INFO);
        $newFriendInviteInfo = $newFriendInviteInfoList->getElement(GameConst::INVITE_FRIEND_PRIMARY_KEY);

        $invitationOnce = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'InvitationOnce', true);
        if (!$invitationOnce) {
            $invitationOnce = array('value' => 0);
        }

        $invitationOnce = $invitationOnce['value'];

        $newFriendInviteInfo->updateLevel($invitationOnce);
        $newFriendInviteInfoList->updateElement(GameConst::INVITE_FRIEND_PRIMARY_KEY,$newFriendInviteInfo);

        SzPersister::get()->setVoList($newFriendInviteInfoList);
        SzPersister::get()->setVoList($newFriendInviteList);

        return;

    }
}